Wechat Mini | Note-1

微信小程序开发 Note-1

@ 2018年8月15日 15:46:28


微信小程序是什么

是一种全新的连接用户和服务的方式,可以在微信内便捷的获取和传播,同时具有出色的使用体验;

手机端APP的另一种全新的展现形式;

不是HTML5应用;

无须下载过多占用手机内存的app,即开即用;

必备技术栈:HTML,JS,CSS;

不是所有app都适用于小程序;

基于腾讯庞大的社交群体,为原生APP导流;

创业公司优先推出小程序,开发成本低;

当作简单的工具使用,需要在APP上频繁的CRUD不适用;


小程序注册流程

邮箱,小程序基本设置,开发者设置;

小程序开发

hello-world

下载微信开发工具后,建立快速开发基本模版即可开启第一个小程序项目;

app.js 只有唯一一个;

pages是页面目录;

wxml-html,js-js,wxss-css;

官方demo

体验小程序

包含了小程序的官方组件以及接口;


小程序工程的构成

基本文件(app.js,app.json,app.wxss)

​ ·app.js 外部全局主要的JS文件,当作一个JS文件的父类

​ ·app.json 全局的配置文件

​ ·app.wxss 全局的页面样式文件

页面文件(Page目录下)

​ `index(index.js,index.wxml,index.wxss,index.json)

​ xxx.js 私有的JS,相当于的子类

​ xxx.json 以json对象形式存在的配置

​ xxx.wxml 页面文件

​ xxx.wxss 私有的页面样式文件


第一个小程序demo

删除部分不需要的文件;

只保留app.js中的部分内容;

app.json 配置项列表-window

1
2
3
4
5
//app.js
App({
onLaunch: function () {
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//app.json
{
"pages": [
"pages/imooc/imooc",
"pages/index/index"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "black"
},
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "首页"
}
]
}
}
在pages,用于描述当前小程序所有页面路径,这是为了让微信客户端知道当前你的小程序页面定义在哪个目;
在pages,设置的第一行,为打开小程序所显示的主页;

window字段:定义小程序所有页面的顶部背景颜色,文字颜色定义等;

在tabBar中,暂时为导航栏;
在networkTimeout字段,各类网络请求的超时时间;

数据绑定以及CSS文件
1
2
3
4
5
<!--index.wxml-->
<view class="container">
<text class="txt-css">{{mydata}}</text>
</view>
{{xxx}} 数据绑定的用法;
1
2
3
4
5
6
7
//index.js
//获取应用实例
Page({
data: {
mydata: 'Data Bind'
}
})
1
2
3
4
//index.wxss
.txt-css{
margin-top: 150rpx;
}
  • rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//外部css文件导入 以及 内联样式
@import "out.wxss";
.txt-css{
margin-top: 150rpx;
}
// out.wxss
.txt-left{
margin-left: 350rpx;
}

<!--index.wxml-->
<view class="container">
<text class="txt-css txt-left" style="color:{{color}};">{{mydata}}</text>
</view>

//index.js
//获取应用实例
Page({
data: {
mydata: 'Data Bind',
color: "red"
},
onLoad:function(){
}
})

小程序页面加载

默认加载pages中的第一个目录;

其他目录需要通过触发才能加载;


小程序APP的生命周期

onLaunch:初始化事件,只被执行一次;

onShow:随着onLaunch触发,打开到小程序前台触发的事件;

onHide:小程序随着前台到后台的转变,隐藏到后台的触发事件;

onError:抛出异常时触发的事件;

其他:开发人员定义的事件;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// app.js
App({
onLaunch: function(options) {
console.log("触发onLaunch")
},
onShow: function(options) {
console.log("触发onShow")
},
onHide: function() {
// Do something when hide.
},
onError: function(msg) {
console.log(msg)
},
globalData: 'I am global data',
courseName: '小程序'
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 全局的 getApp() 函数可以用来获取到小程序实例
Page({
data: {
mydata: 'imooc Bind',
color: "green"
},
onLoad: function() {
var appInstance = getApp()
console.log(appInstance.courseName)
this.setData({
mydata: appInstance.courseName
});
}
})

手机端的远程调试

进行手机上的远程调试(debug)时,需要在创建工程时,填上AppID;

使用手机扫描小程序开发根据提供的预览和远程调试的功能;


私有页面的生命周期以及导航

注册页面,生命周期回调函数

onLoad(Object query) 页面加载时触发

onShow() 页面显示/切入前台时触发

onReady() 页面初次渲染完成时触发

onHide() 页面隐藏/切入后台时触发

onUnload() 页面卸载时触发

关于onHide和onUnload,联系到两个API wx.redirectTo(OBJECT) 和 wx.navigateTo(OBJECT)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 在页面中写入一个clickMe的点击事件;
Page({
clickMe:function(){
wx.navigateTo({
url: '../index/index',
}),
wx.redirectTo({
url: '../index/index',
})
}
})
// 注意事项1 url的路径问题,明确相对路径和绝对路径;
// 当跳转当另一页面,点击返回时,只触发了onShow事件,没有触发onLaunch和onReady事件;
// redirectTo事件,触发onUnload事件;
// 注意事项2 减少使用navigateTo,防止onHide消耗过多的资源;


小程序的事件触发

事件

通过行为进行的人机交互的方式;

类似html中onClickonChange事件等;

bindtap,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。

1
2
3
4
<!-- event.wxml-->
<view class="container">
<view id="tapTest" bindtap="clickMe"> Click me! </view>
</view>
1
2
3
4
5
6
7
8
9
// event.js
Page({
data: {
},
clickMe: function(e) {
console.log("Click Me Was Clicked");
console.log(e);
}
})
事件分类

事件分为冒泡事件非冒泡事件

​ ·冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递;

​ ·非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递;


小程序的模块化

抽离通用方法作为通用函数;

构建utils-common类;

可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者 exports 才能对外暴露接口;

1
2
3
4
5
6
7
8
9
10
// common.js
function sayHello(name) {
console.log('Hello ' + name + '!')
}
function sayGoodbye(name) {
console.log(`Goodbye ${name} !`)
}
// 区别单引号''和反引号``
module.exports.sayHello = sayHello
exports.sayGoodbye = sayGoodbye

在需要使用这些模块的文件中,使用 require(path) 将公共代码引入 ;

1
2
3
4
5
6
7
8
9
var common = require('common.js')
Page({
helloMINA: function() {
common.sayHello('MINA')
},
goodbyeMINA: function() {
common.sayGoodbye('MINA')
}
})

视图层——数据绑定

HTML中,JQuery dom操作 $选择器;

WX中,通过数据绑定 类似于vue/react,通过Mustache表达式;

作用范围:内容,组件属性(双引号内),控制属性(双引号内),关键字(双引号内);

1
2
3
4
5
6
7
8
<!--pages/dataBind/dataBind.wxml-->
<view class='container' id="myid-{{testid}}">
{{msg}}
<checkbox checked="{{true}}"> </checkbox>
<checkbox checked="{{false}}"> </checkbox>
<checkbox checked="{{flag}}"> </checkbox>
<checkbox checked="{{unflag}}"> </checkbox>
</view>
1
2
3
4
5
6
7
8
9
10
11
12
// pages/dataBind/dataBind.js
Page({
data: {
msg:"这是一个msg",
testid:1001,
flag:true,
unflag:false,
a:1,
b:2,
c:3
}
})
1
2
3
4
5
6
7
8
9
10
<!-- 三元运算 -->
<view hidden="{{flag ? true : false}}"> Hidden </view>
<!-- 算数运算 -->
<view> {{a + b}} + {{c}} + d </view>
view中的内容为 3 + 3 + d
<!-- 字符串运算 -->
<view>{{msg + hello + "test"}}</view>
view中内容为 这是一个msghellotest
<view>{{a+b + hello}}</view>
view中内容为 3hello

视图层——列表渲染

wx:key

如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态

wx:key 的值以两种形式提供

  1. 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
  2. 保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字,如:

当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率

视图层——条件渲染

wx:if

在框架中,使用 wx:if="" 来判断是否需要渲染该代码块,也可以用 wx:elifwx:else 来添加一个 else 块:

1
2
3
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
block wx:if

因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 <block/> 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。

1
2
3
4
<block wx:if="{{true}}">
<view> view1 </view>
<view> view2 </view>
</block>

注意: <block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。

wx:if vs hidden

因为 wx:if 之中的模板也可能包含数据绑定,所以当 wx:if 的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。

同时 wx:if 也是惰性的,如果在初始渲染条件为 false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染

相比之下,hidden 就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏

一般来说,wx:if 有更高的切换消耗而 hidden 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则 wx:if 较好


通用模板的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!-- 定义模板
使用 name 属性,作为模板的名字。然后在<template/>内定义代码片段-->
<template name="mytemp">
<view>姓名:{{name}}</view>
<view>年龄:{{age}}</view>
<view>地址:{{address}}</view>
<view>备注:{{remark}}</view>
<view>{{msg}}</view>
</template>
<!-- 使用模板
is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入
is 属性可以使用 Mustache 语法,来动态决定具体需要渲染哪个模板 -->
<view class='container'>
<template is="mytemp" data="{{...person,msg,name:'rex',age:'18'}}" />
<template is="mytemp" data="{{...person,msg,name:'rex',age:'18'}}" />
</view>

<!--temp.js-->
Page({
data: {
person:{
address:"BEIJING",
remark:"This is a Template"
},
msg:"This is a Msg"
}
})

wxs模块——页面引用/模块调用模块

WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构;

wxs 不依赖于运行时的基础库版本,可以在所有版本的小程序中运行;
wxs 与 javascript 是不同的语言,有自己的语法,并不和 javascript 一致;
wxs 的运行环境和其他 javascript 代码是隔离的,wxs 中不能调用其他 javascript 文件中定义的函数,也不能调用小程序提供的API;
wxs 函数不能作为组件的事件回调;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// module.wxs
var num2 = require("../wxs/num2.wxs");
var name = 'imooc';
var age = 18;
var method = function(obj) {
console.log(num2.name);
console.log(num2.age);
console.log(num2.method("num2"));
return obj;
}
module.exports = {
name: name,
age: age,
method: method
}
// num2.wxs
var name = 'imooc2';
var age = 20;
var method = function(obj) {
return obj;
}
module.exports = {
name: name,
age: age,
method: method
}
1
2
3
4
5
6
7
8
// wxs.wxml
<view class="container">
<!-- 页面级别的引用 -->
<wxs src="../wxs/module.wxs" module="item"></wxs>
<view>{{item.name}}</view>
<view>{{item.age}}</view>
<view>{{item.method("这是一个参数")}}</view>
</view>

模版的外部引用

模版在某个wxml中定义完毕后,可以被其他页面引用;

关键字import;

import 有作用域的概念,即只会 import 目标文件中定义的 template,而不会 import 目标文件 import 的 template,即不支持间接传递引用(A引用B,B引用C,A不能引用C);

WXML 提供两种文件引用方式importinclude

1
2
3
4
5
<view class="container">
<!-- 模版的外部引用 -->
<import src="../temp/temp.wxml"/>
<template is="mytemp" data="{{name:'imooc',age:'18',...person,msg}}"/>
</view>

页面引用外部wxml通用页面

HTML页面常分为Header,Body,Footer;

定义通用的Header和Footer;

关键字include;

include 可以将目标文件除了 <template/> <wxs/> 外的整个代码引入,相当于是拷贝到 include 位置;

1
2
3
4
5
6
7
8
<!-- index.wxml -->
<include src="header.wxml"/>
<view> body </view>
<include src="footer.wxml"/>
<!-- header.wxml -->
<view> header </view>
<!-- footer.wxml -->
<view> footer </view>

@ 2018年8月15日 20:41:52